`include "defines.v"
module ysyx_210448_cpu(
input clock,
input reset, 
input [3:0] axi_r_id_i,
input [3:0] axi_b_id_i,
input [3:0] axi_r_id,
input axi_read_ready,
input [63:0] axi_data_read,
input [1:0] axi_resp,
input [63:0] mtimecmp_data,
input mtimecmp_open,
input [63:0] mtime_data,
input mtime_open,
input clint_skip,
input r_hs,
input b_hs,
input [63:0] r_data,
input r_valid,
output  axi_read_valid,
output [63:0] axi_read_addr,
output [1:0] axi_size,
output [63:0] axi_write_data,
output [63:0] axi_write_addr,
output [7:0] axi_write_mask,
output [3:0] axi_id,
output axi_mem_write,
output mem_write,
output io_uart_out_valid,
output [7:0] io_uart_out_ch
);
wire if_id_bubble;
wire id_exe_bubble;
//if_stage
wire if_ar_hand;
wire [63:0]pc_add;
wire pc_write;
wire if_ar_valid;
wire [63 : 0] if_pc;
wire [31 : 0] if_inst;
wire [63:0] if_pc_if;
wire [31:0] if_inst_if;
wire if_stop;
wire if_fetched;
wire handshake_done;
//IF_ID
wire if_id_en;
wire if_clk;
wire [63 : 0] id_pc;
wire [31 : 0] id_inst;
//id_stage
wire [4 : 0]id_rd;
wire [6:0] id_opcode;
wire [19 : 0]id_u_imm;
wire [19 : 0]id_j_imm;
wire [11 : 0]id_j_imm_j;
wire [11 : 0]id_i_imm;
wire [11 : 0]id_I_imm;
wire [6 : 0]id_b_imm;
wire [6 : 0]id_s_imm;
wire [4 : 0]id_s_imm_s;
wire [4 : 0]id_b_imm_b;
wire [11:0]id_w_imm;
wire [5:0]id_w_shamt;
wire [2:0] id_s1;
wire id_s2;
wire [5:0]id_shamt;
wire [11:0]id_csr;
wire [4:0]id_zimm;
wire id_csr_read;
wire id_csr_write;
wire [63:0] id_op1;
wire [63:0] id_op2;
wire id_ena1;
wire id_ena2;
wire [4:0]id_rs1;
wire [4:0]id_rs2;
//ID_EXE

wire [63:0] id_t;
wire id_open;
wire exe_open;
wire [4:0]rs1;
wire [4:0]rs2;
wire [63:0] id_pc_id;
wire [31:0] id_inst_id;
wire [6:0] id_opcode_id;
wire id_exe_en;
wire [63:0] exe_pc;
wire [31:0] exe_inst;
wire [63:0] exe_op1;
wire [63:0] exe_op2;
wire [4 : 0]exe_rd;
wire [6:0] exe_opcode;
wire [19 : 0]exe_u_imm;
wire [19 : 0]exe_j_imm;
wire [11 : 0]exe_j_imm_j;
wire [11 : 0]exe_i_imm;
wire [11 : 0]exe_I_imm;
wire [6 : 0]exe_b_imm;
wire [6 : 0]exe_s_imm;
wire [4 : 0]exe_s_imm_s;
wire [4 : 0]exe_i_imm_i;
wire [4 : 0]exe_b_imm_b;
wire [11:0]exe_w_imm;
wire [5:0]exe_w_shamt;
wire [2:0] exe_s1;
wire exe_s2;
wire [5:0]shamt;
wire [11:0]exe_csr;
wire [4:0]exe_zimm;
wire exe_csr_read;
wire exe_csr_write;
//exe_stage
wire exe_pc_write;
wire [63:0]exe_t;
wire [4:0]exe_zimm;
wire [63:0]exe_csr_data;
wire [`REG_BUS] exe_data;
wire exe_w_ena;
wire exe_skip;
//EXE_MEM
wire mem_open;
wire exe_mem_en;
wire [63:0]mem_pc;
wire [31:0] mem_inst;
wire [6:0]mem_opcode;
wire [6:0]mem_s_imm;
wire [4:0]mem_s_imm_s;
wire [63:0]mem_op1;
wire [63:0]mem_op2;
wire [11:0] mem_I_imm;
wire [2:0] mem_s1;
wire [63:0] mem_data;
wire mem_w_ena;
wire [63:0] mem_csr_data;
wire mem_csr_read;
wire mem_csr_write;
wire [11:0] mem_csr;
wire [63:0] mem_data;
//mem_stage
wire mem_skip;
wire mem_ok;
wire mem_read;
wire [63:0] mem_read_data;
//MEM_WB
wire wb_skip;
wire wb_open;
wire [4:0] mem_rd;
wire mem_wb_en;
wire [63:0]wb_pc;
wire [31:0] wb_inst;
wire wb_w_ena;
wire [4:0] wb_rd;
wire [`REG_BUS] wb_data;
wire wb_read;
wire [63:0]wb_read_data;
wire [11:0]wb_csr;
wire wb_csr_write;
wire wb_csr_read;
wire [63:0] wb_csr_data;
wire [6:0] wb_opcode;

//wb_stage
wire ena2;
wire csr_skip;
wire wb_ok;
wire [63:0]t;
wire [`REG_BUS] regs_o[0 : 31];
wire [63:0] mstatus;	
wire [63:0] mepc;
wire [63:0] mtvec;
wire [63:0] mcause;
wire [63:0] mip;
wire [63:0] mie;
wire [63:0] mcause_data;
wire [63:0] mstatus_data;
wire [63:0] rmstatus;
wire [63:0] pc_add;
wire pc_write;
//csr
wire [63:0] mcycle;
wire [63:0] mscratch;
wire [63:0] sstatus;
wire id_csr_skip;
wire exe_csr_skip;
wire mem_csr_skip;
wire wb_csr_skip;
wire c_interrupt;
wire [63:0] exe_pc_add;
wire exe_pc_write;
wire [63:0] mhartid;
wire [63:0] csr_pc_add;
wire csr_pc_write;
//axi
wire if_fetched;
wire id_fetched;
wire exe_fetched;
wire mem_fetched;
wire wb_fetched;
wire [63:0] mem_read_addr;
wire [63:0] rdata;
wire [63:0] if_data_read;
wire [63:0] if_addr;
wire [3:0] if_read_id;
wire [3:0] mem_read_id;
wire if_axi_stop;
wire axi_mem_read;
wire wb_mem_read;
wire mem_read_close;
wire wb_write;
wire l_double;
wire close;
wire wb_close;
wire if_mem_read;
wire id_mem_read;
wire exe_mem_read;
wire mem_mem_read;
wire ena1;
wire [2:0]s3;
wire wb_write_ready;
wire mem_write_ready;
wire mem_mem_write;
wire if_mem_write;
wire id_mem_write;
wire if_w_ena;
wire id_w_ena;
wire ld;
wire [63:0] p_exe_op1;
wire [63:0] p_exe_op2;
wire p_ready1;
wire p_ready2;


ysyx_210448_cpu_abtiter ysyx_210448_cpu_abtiter(
.clk(clock),
.rst(reset),
.if_read_id(if_read_id),
.mem_read_id(mem_read_id),
.pc_write(pc_write),
.pc_add(pc_add),
.exe_pc_write(exe_pc_write),
.exe_pc_add(exe_pc_add),
.csr_pc_write(csr_pc_write),
.csr_pc_add(csr_pc_add),
.axi_id(axi_id),
.if_inst(if_inst),
.wb_read(wb_read),
.axi_r_id_i(axi_r_id_i),
.axi_r_id(axi_r_id),
.axi_mem_read(axi_mem_read),
.mem_read(mem_read),
.if_addr(if_addr),
.if_ar_valid(if_ar_valid),
.r_hs(r_hs),
.r_data(r_data),
.mem_read_addr(mem_read_addr),
.axi_read_ready(axi_read_ready),
.axi_data_read(axi_data_read),
.if_read_data(if_data_read),
.mem_read_data(rdata),
.axi_read_valid(axi_read_valid),
.axi_addr(axi_read_addr),
.axi_size(axi_size),
.handshake_done(handshake_done),
.stop(if_stop),
.mem_wb_en(mem_wb_en),
.mem_read_close(mem_read_close)
);

ysyx_210448_if_stage ysyx_210448_if_stage(
.clk(clock),
.rst(reset),
.r_hs(r_hs),
.pc_add(pc_add),
.pc_write(pc_write),
.if_ar_hand(if_ar_hand),
.axi_mem_read(axi_mem_read),
.axi_mem_write(axi_mem_write),
.if_read_id(if_read_id),
.if_pc(if_pc),
.if_w_ena(if_w_ena),
.if_inst(if_inst),
.if_id_en(if_id_en),
.stop(if_stop),
.if_ready(axi_read_ready),
.if_mem_read(if_mem_read),
.if_data_read(if_data_read),
.if_valid(if_ar_valid),
.if_addr(if_addr),
.if_size(axi_size),
.if_fetched(if_fetched)
);
ysyx_210448_IF_ID ysyx_210448_IF_ID(
.clk(clock),
.rst(reset),
.if_pc(if_pc),
.if_inst(if_inst),
.if_w_ena(if_w_ena),
.if_mem_read(if_mem_read),
.id_mem_read(id_mem_read),
.if_fetched(if_fetched),
.id_pc(id_pc),
.id_inst(id_inst),
.id_w_ena(id_w_ena),
.if_id_en(if_id_en),
.if_id_bubble(if_id_bubble),
.id_fetched(id_fetched)
);
ysyx_210448_id_stage ysyx_210448_id_stage(
.clk(clock),
.rst(reset),
.id_inst(id_inst),
.id_rd(id_rd),
.if_pc(if_pc),
.id_opcode(id_opcode),
.id_u_imm(id_u_imm),
.id_j_imm(id_j_imm),
.id_j_imm_j(id_j_imm_j),
.id_i_imm(id_i_imm),
.id_I_imm(id_I_imm),
.id_b_imm(id_b_imm),
.id_s_imm(id_s_imm),
.id_s_imm_s(id_s_imm_s),
.id_b_imm_b(id_b_imm_b),
.id_w_imm(id_w_imm),
.id_w_shamt(id_w_shamt),
.id_s1(id_s1),
.id_s2(id_s2),
.id_shamt(id_shamt),
.id_csr(id_csr),
.id_zimm(id_zimm),
.id_csr_read(id_csr_read),
.id_csr_write(id_csr_write),
.id_rs1(id_rs1),
.id_rs2(id_rs2),
.id_ena1(id_ena1),
.id_ena2(id_ena2),
.id_exe_en(id_exe_en)
);
//stop信号，暂停流水线，open信号，开启流水线，如果stop=1,则 发出一个open信号随着流水线传递下去，直到wb阶段，将wb_ok置1,流水线开始

ysyx_210448_pause ysyx_210448_Pause(
  .clk(clock),
  .rst(reset),
  .ld(ld),
  .ena1(ena1),
  .ena2(ena2),
  .if_fetched(if_fetched),
  .id_ena1(id_ena1),
  .id_ena2(id_ena2),
  .regs_o(regs_o),
  .id_fetched(id_fetched),
  .exe_opcode(exe_opcode),
  .mem_opcode(mem_opcode),
  .exe_data(exe_data),
  .mem_data(mem_data),
  .wb_data(wb_data),
  .p_exe_op1(p_exe_op1),
  .p_exe_op2(p_exe_op2),
  .p_ready1(p_ready1),
  .p_ready2(p_ready2),
  .wb_ok(wb_ok),
  .id_rs1(id_rs1),
  .id_rs2(id_rs2),
  .exe_rd(exe_rd),
  .mem_rd(mem_rd)
);

ysyx_210448_ID_EXE ysyx_210448_ID_EXE(
.clk(clock),
.rst(reset),
.id_pc(id_pc),
.id_inst(id_inst),
.id_fetched(id_fetched),
.id_csr_skip(id_csr_skip),
.id_mem_read(id_mem_read),
.id_w_ena(id_w_ena),
.id_op1(id_op1),
.id_op2(id_op2),
.id_t(id_t),
.id_rs1(id_rs1),
.id_rs2(id_rs2),
.id_rd(id_rd),
.id_opcode(id_opcode),
.id_u_imm(id_u_imm),
.id_j_imm(id_j_imm),
.id_j_imm_j(id_j_imm_j),
.id_i_imm(id_i_imm), 
.id_I_imm(id_I_imm),
.id_b_imm(id_b_imm),
.id_s_imm(id_s_imm),
.id_s_imm_s(id_s_imm_s),
.id_b_imm_b(id_b_imm_b),
.id_w_imm(id_w_imm),
.id_w_shamt(id_w_shamt),
.id_s1(id_s1),
.id_s2(id_s2),
.id_shamt(id_shamt),
.id_csr(id_csr),
.id_zimm(id_zimm),
.id_csr_read(id_csr_read),
.id_csr_write(id_csr_write),
.exe_csr_skip(exe_csr_skip),
.exe_pc(exe_pc),
.exe_inst(exe_inst),
.exe_fetched(exe_fetched),
.exe_mem_read(exe_mem_read),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_t(exe_t),
.exe_rd(exe_rd),
.exe_w_ena(exe_w_ena),
.exe_opcode(exe_opcode),
.exe_u_imm(exe_u_imm),
.exe_j_imm(exe_j_imm),
.exe_j_imm_j(exe_j_imm_j),
.exe_i_imm(exe_i_imm), 
.exe_I_imm(exe_I_imm),
.exe_b_imm(exe_b_imm),
.exe_s_imm(exe_s_imm),
.exe_s_imm_s(exe_s_imm_s),
.exe_i_imm_i(exe_i_imm_i),
.exe_b_imm_b(exe_b_imm_b),
.exe_w_imm(exe_w_imm),
.exe_w_shamt(exe_w_shamt),
.exe_s1(exe_s1),
.exe_s2(exe_s2),
.exe_shamt(shamt),
.exe_csr(exe_csr),
.exe_zimm(exe_zimm),
.exe_csr_read(exe_csr_read),
.exe_csr_write(exe_csr_write),
.id_exe_en(id_exe_en),
.id_exe_bubble(id_exe_bubble),
.rs1(rs1),
.rs2(rs2)
);
ysyx_210448_exe_stage ysyx_210448_exe_stage(
.clk(clock),
.rst(reset),
.io_uart_out_valid(io_uart_out_valid),
.io_uart_out_ch(io_uart_out_ch),
.s3(s3),
.p_exe_op1(p_exe_op1),
.p_exe_op2(p_exe_op2),
.p_ready1(p_ready1),
.p_ready2(p_ready2),
.exe_fetched(exe_fetched),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_rd(exe_rd),
.exe_pc(exe_pc),
.exe_inst(exe_inst),
.exe_opcode(exe_opcode),
.exe_mem_read(exe_mem_read),
.mem_mem_read(mem_mem_read),
.r_hs(r_hs),
.axi_r_id_i(axi_r_id_i),
.mem_read(mem_read),
.exe_u_imm(exe_u_imm),
.exe_j_imm(exe_j_imm),
.exe_j_imm_j(exe_j_imm_j),
.exe_i_imm(exe_i_imm),
.exe_b_imm(exe_b_imm),
.exe_s_imm(exe_s_imm),
.exe_s_imm_s(exe_s_imm_s),
.exe_i_imm_i(exe_i_imm_i),
.exe_I_imm(exe_I_imm),
.exe_w_imm(exe_w_imm),
.exe_w_shamt(exe_w_shamt),
.shamt(shamt),
.exe_b_imm_b(exe_b_imm_b),
.exe_s1(exe_s1),
.exe_s2(exe_s2),
.exe_t(exe_t),
.exe_zimm(exe_zimm),
.exe_csr_data_re(mem_csr_data),
.exe_data_re(mem_data),
.exe_w_ena(exe_w_ena),
.exe_skip(exe_skip),
.exe_pc_add_re(exe_pc_add),
.exe_pc_write(exe_pc_write),
.exe_mem_en(exe_mem_en),
.if_id_bubble(if_id_bubble),
.id_exe_bubble(id_exe_bubble)
);
ysyx_210448_EXE_MEM ysyx_210448_EXE_MEM(
.clk(clock),
.rst(reset),
.exe_skip(exe_skip),
.exe_csr_skip(exe_csr_skip),
.exe_open(exe_open),
.exe_pc(exe_pc),
.exe_inst(exe_inst),
.exe_fetched(exe_fetched),
.exe_mem_read(exe_mem_read),
.exe_rd(exe_rd),
.exe_opcode(exe_opcode),
.exe_s_imm(exe_s_imm),
.exe_s_imm_s(exe_s_imm_s),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_I_imm(exe_I_imm),
.exe_s1(exe_s1),
//.exe_data(exe_data),
.exe_w_ena(exe_w_ena),
.exe_csr(exe_csr),
//.exe_csr_data(exe_csr_data),
.exe_csr_read(exe_csr_read),
.exe_csr_write(exe_csr_write),
.mem_open(mem_open),
.mem_skip(mem_skip),
.mem_fetched(mem_fetched),
.mem_csr_skip(mem_csr_skip),
.mem_pc(mem_pc),
.mem_inst(mem_inst),
.mem_mem_read(mem_mem_read),
.mem_rd(mem_rd),
.mem_opcode(mem_opcode),
.mem_s_imm(mem_s_imm),
.mem_s_imm_s(mem_s_imm_s),
.mem_op1(mem_op1),
.mem_op2(mem_op2),
.mem_I_imm(mem_I_imm),
.mem_s1(mem_s1),
//.mem_data(mem_data),
.mem_w_ena(mem_w_ena),
.mem_csr(mem_csr),
//.mem_csr_data(mem_csr_data),
.mem_csr_read(mem_csr_read),
.mem_csr_write(mem_csr_write),
.exe_mem_en(exe_mem_en)
);
ysyx_210448_mem_stage ysyx_210448_mem_stage(
.clk(clock),
.rst(reset),
.axi_r_id_i(axi_r_id_i),
.b_hs(b_hs),
.stop(if_stop),
.mem_fetched(mem_fetched),
.s3(s3),
.wb_write(wb_write),
.axi_read_ready(axi_read_ready),
.mem_write_ready(mem_write_ready),
.mem_read_id(mem_read_id),
.handshake_done(handshake_done),
.mem_open(mem_open),
.mem_pc(mem_pc),
.mem_inst(mem_inst),
.mem_rd(mem_rd),
.mem_opcode(mem_opcode),
.exe_opcode(exe_opcode),
.mem_s_imm(mem_s_imm),
.mem_s_imm_s(mem_s_imm_s),
.mem_op1(mem_op1),
.mem_op2(mem_op2),
.mem_I_imm(mem_I_imm),
.mem_s1(mem_s1),
.mem_read(mem_read),
.mem_read_addr(mem_read_addr),
.rdata(rdata),
.mem_read_data(mem_read_data),
.mem_write_addr(axi_write_addr),
.wmask(axi_write_mask),
.wdata(axi_write_data),
.axi_mem_write(axi_mem_write),
.mem_wb_en(mem_wb_en),
.mem_write(mem_write),
.wb_write_ready(wb_write_ready)
);
ysyx_210448_MEM_WB ysyx_210448_MEM_WB(
.clk(clock),
.rst(reset),
.close(close),
.mem_write_ready(mem_write_ready),
.mem_write(mem_write),
.mem_skip(mem_skip),
.mem_csr_skip(mem_csr_skip),
.mem_open(mem_open),
.mem_wb_en(mem_wb_en),
.mem_pc(mem_pc),
.mem_inst(mem_inst),
.mem_fetched(mem_fetched),
.mem_w_ena(mem_w_ena),
.mem_rd(mem_rd),
.mem_data(mem_data),
.mem_read(mem_read),
.mem_read_data(mem_read_data),
.mem_csr(mem_csr),
.mem_csr_write(mem_csr_write),
.mem_csr_read(mem_csr_read),
.mem_csr_data(mem_csr_data),
.mem_opcode(mem_opcode),
.wb_skip(wb_skip),
.wb_write_ready(wb_write_ready),
.wb_csr_skip(wb_csr_skip),
.wb_fetched(wb_fetched),
.wb_open(wb_open),
.wb_write(wb_write),
.wb_pc(wb_pc),
.wb_inst(wb_inst),
.wb_w_ena(wb_w_ena),
.wb_rd(wb_rd),
.wb_data(wb_data),
.wb_read(wb_read),
.wb_read_data(wb_read_data),
.wb_csr(wb_csr),
.wb_csr_write(wb_csr_write),
.wb_csr_read(wb_csr_read),
.wb_csr_data(wb_csr_data),
.wb_opcode(wb_opcode),
.wb_close(wb_close)
);
ysyx_210448_wb_stage ysyx_210448_wb_stage(
.clk(clock),
.rst(reset),
.ld(ld),
.wb_inst(wb_inst),
.mem_fetched(mem_fetched),
.mem_read(mem_read),
.if_pc(if_pc),
.exe_pc_write(exe_pc_write),
.exe_fetched(exe_fetched),
.exe_pc_add(exe_pc_add),
.if_fetched(if_fetched),
.if_ar_hand(if_ar_hand),
.mtimecmp_data(mtimecmp_data),
.mtimecmp_open(mtimecmp_open),
.mtime_data(mtime_data),
.mtime_open(mtime_open),
.clint_skip(clint_skip),
.wb_fetched(wb_fetched),
.wb_close(wb_close),
.exe_w_ena(exe_w_ena),
.id_ena1(id_ena1),
.id_ena2(id_ena2),
.id_rs1(id_rs1),
.id_rs2(id_rs2),
.id_op1(id_op1),
.id_op2(id_op2),
.wb_open(wb_open),
.wb_ok(wb_ok),
.wb_pc(wb_pc),
.if_w_ena(if_w_ena),
.wb_w_ena(wb_w_ena),
.wb_rd(wb_rd),
.wb_data(wb_data),
.wb_read(wb_read),
.axi_mem_read(axi_mem_read),
.axi_mem_write(axi_mem_write),
.wb_read_data(wb_read_data),
.id_csr(id_csr),
.wb_csr(wb_csr),
.wb_csr_write(wb_csr_write),
.id_csr_read(id_csr_read),
.wb_csr_data(wb_csr_data),
.id_t(id_t),
.regs_o(regs_o),
.mstatus(mstatus),
.sstatus(sstatus),	
.mepc(mepc),
.mtvec(mtvec),
.mcause(mcause),
.mhartid(mhartid),
.mip(mip),
.mie(mie),
.clock_interrupt(clock_interrupt),
.mstatus_data(mstatus_data),
.mscratch(mscratch),
.id_csr_skip(id_csr_skip),
.mcycle(mcycle),
.mcause_data(mcause_data),
.rmstatus(rmstatus),
.csr_pc_add(csr_pc_add),
.csr_pc_write(csr_pc_write),
.ena1(ena1),
.ena2(ena2)
);

// Difftest
wire clock_interrupt;
reg cmt_wen;
reg [7:0] cmt_wdest;
reg [`REG_BUS] cmt_wdata;
reg [`REG_BUS] cmt_pc;
reg [31:0] cmt_inst;
reg cmt_valid;
reg trap;
reg [7:0] trap_code;
reg [63:0] cycleCnt;
reg [63:0] instrCnt;
reg skip;
reg [`REG_BUS] regs_diff [0 : 31];
reg [31:0] intrNO;
reg [31:0] cause;
//csr
reg [63:0] mtvec_diff;
reg [63:0] mstatus_diff;
reg [63:0] sstatus_diff;
reg [63:0] mepc_diff;
reg [63:0] mcause_diff;
reg [63:0] mip_diff;
reg [63:0] mie_diff;  
reg [63:0] mscratch_diff;
reg [63:0] mcause_data;
reg [63:0] mstatus_data;
reg [63:0] mcause_arch;
reg [63:0] mhartid_diff;
reg [63:0] rmstatus_diff;
wire [63:0] interrupt_pc;
reg interrupt_ready1;
reg interrupt_ready2;
reg [63:0] mepc_exe;
wire interrupt;
reg [63:0] mstatus_diff_diff;
reg [63:0] mret;
reg csr;
always @(posedge clock) begin
  if(cmt_valid)
  interrupt_ready1<=1'b1;
  else if(if_fetched) 
  interrupt_ready1<=1'b0;
  if(clock_interrupt)
  interrupt_ready2<=1'b1;
  else if(interrupt)
  interrupt_ready2<=1'b0;
  if(interrupt)
  csr<=1'b0;
  else if(wb_fetched)
  csr<=1'b1;
  if((mem_fetched)&&(exe_pc_write))
  begin
    mepc_exe<=exe_pc_add;
  end
  else if(if_fetched)
  begin
    mepc_exe<=if_pc+4;
  end
end
//assign interrupt_pc=(interrupt_ready)?mepc:wb_pc;
assign interrupt=(interrupt_ready1)?interrupt_ready2:0;
assign interrupt_pc=mepc;

wire ecall_valid=(wb_opcode==7'b1110011&&wb_csr==12'h000)?0:1;
wire clock_valid=(clock_interrupt)?0:((if_fetched)?1:0);
wire inst_valid = (interrupt)?0:(wb_inst!= 0)&&((wb_pc!=cmt_pc)|(wb_inst!=cmt_inst));//&&(wb_fetched);// (wb_pc != `PC_START) |//(wb_opcode==7'b1110011&&wb_csr==12'h000)?ecall_valid:
reg mstatus_mie;
reg mstatus_mpie;
reg interrupt_mie;
reg [1:0] mstatus_fs;
  wire [1:0] mpp=2'b11;
always @(negedge clock) begin
  if (reset) begin
    {cmt_wen, cmt_wdest, cmt_wdata, cmt_pc, cmt_inst, cmt_valid, trap, trap_code, cycleCnt, instrCnt} <= 0;
  end
  else if (~trap) begin//
    cmt_wen <= (clint_skip)?1:wb_w_ena;
    cmt_wdest <= {3'd0, wb_rd};
    cmt_wdata <=(wb_read==1'b1)?wb_read_data:wb_data;
    cmt_pc <= wb_pc;
    cmt_inst <= wb_inst;
    cmt_valid <= inst_valid;
		regs_diff <= regs_o;
    trap <= wb_inst[6:0] == 7'h6b;
    trap_code <= regs_o[10][7:0];
    cycleCnt <= cycleCnt + 1;
    instrCnt <= instrCnt + inst_valid;
    skip<=(clint_skip)?clint_skip:(((wb_csr_read)?wb_csr_skip:wb_skip));

    //csr difftest
    if((wb_opcode==7'b1110011)&&csr) begin
    case(wb_csr)
    12'h000:begin if(id_csr==12'h000) begin mepc_diff<=wb_pc;mcause_diff<=mcause_data;mstatus_mpie<=mstatus_mie;mstatus_diff<={{mstatus[63:13]},{mpp[1:0]},
    {mstatus[10:8]},{mstatus_mie},{mstatus[6:4]},{1'b0},{mstatus[2:0]}};mstatus_fs<=mstatus[14:13];rmstatus_diff<=mstatus_diff; end end
    12'h305:mtvec_diff<=wb_csr_data;
    12'h341:if(id_rs1!=5'b0) mepc_diff<=wb_csr_data;
    12'h300:begin if (id_rs1!=5'b0) begin  mstatus_diff<={{wb_csr_data[13]},{wb_csr_data[62:0]}}; 
    sstatus_diff<={{wb_csr_data[13]},{wb_csr_data[62:15]},{wb_csr_data[14:13]},{13{1'b0}}}; 
    if(((id_rs1!=5'b0)&&(wb_rd!=5'b0))||((mstatus_diff[13])&&(wb_rd==5'b0))) 
    begin mstatus_mie<=mstatus_diff[3]; rmstatus_diff<=mstatus_diff;mstatus_fs<=mstatus_diff[14:13]; mstatus_mpie<=mstatus_diff[7]; end end end
    12'h344:mip_diff<=wb_csr_data;
    12'h304:mie_diff<=wb_csr_data;
    12'h342:mcause_diff<=wb_csr_data;
    12'h340:mscratch_diff<=wb_csr_data;
    12'h302:begin mstatus_diff<=(interrupt)?rmstatus_diff:
    ({{mstatus_fs[0]},{rmstatus_diff[62:15]},{mstatus_fs},{2{1'b0}},{rmstatus_diff[10:8]},{1'b1},
    {rmstatus_diff[6:4]},{mstatus_mpie},rmstatus_diff[2:0]});end//mstatus_mpie//mstatus_mie
    12'hf14:mhartid_diff<=wb_csr_data;
    default:begin mcause_diff<=64'b0;mepc_diff<=64'b0;mstatus_diff<=64'b0; end
    endcase
  end
if(interrupt)
    begin
    //mstatus_mie<=mstatus_diff[3]; 
    rmstatus_diff<=mstatus_diff;
    mstatus_fs<=mstatus_diff[14:13];
    mepc_diff<=(wb_csr==12'h302)?mepc_diff:mepc_exe;
    mcause_diff<=mcause;
    mstatus_mpie<=mstatus_diff[3];
    //interrupt_mie<=(wb_csr==12'h300)?mstatus_mie:mstatus_mpie;
    //mip_diff<={{mip[63:8]},{1'b1},{mip[6:0]}};
    mstatus_diff<=(wb_csr==12'h302)?rmstatus_diff:((wb_csr==12'h300)?
    {{wb_csr_data[63:13]},{mpp[1:0]},{wb_csr_data[10:8]},{wb_csr_data[3]},{wb_csr_data[6:4]},{1'b0},{wb_csr_data[2:0]}}
    :{{mstatus_diff[63:13]},{mpp[1:0]},{mstatus_diff[10:8]},{mstatus_diff[3]},{mstatus_diff[6:4]},{1'b0},{mstatus_diff[2:0]}});
    intrNO<=mcause[31:0];
    cause<=mcause[31:0];
    end
    else begin
    intrNO<=32'b0;
    cause<=32'b0;
    end

  end
end



DifftestInstrCommit DifftestInstrCommit(
  .clock              (clock),
  .coreid             (0),
  .index              (0),
  .valid              (cmt_valid),//cmt_valid
  .pc                 (cmt_pc),
  .instr              (cmt_inst),//cmt_inst
  .skip               (skip),
  .isRVC              (0),
  .scFailed           (0),
  .special            (0),
  .wen                (cmt_wen),
  .wdest              (cmt_wdest),
  .wdata              (cmt_wdata)
); 

DifftestArchEvent DifftestArchEvent(
  .clock(clock),
  .coreid(0),
  .intrNO(intrNO),
  .cause(cause),//mcause_arch[31:0]
  .exceptionPC(interrupt_pc),
  .exceptionInst(cmt_inst)
);

DifftestArchIntRegState DifftestArchIntRegState (
  .clock              (clock),
  .coreid             (0),
  .gpr_0              (regs_diff[0]),
  .gpr_1              (regs_diff[1]),
  .gpr_2              (regs_diff[2]),
  .gpr_3              (regs_diff[3]),
  .gpr_4              (regs_diff[4]),
  .gpr_5              (regs_diff[5]),
  .gpr_6              (regs_diff[6]),
  .gpr_7              (regs_diff[7]),
  .gpr_8              (regs_diff[8]),
  .gpr_9              (regs_diff[9]),
  .gpr_10             (regs_diff[10]),
  .gpr_11             (regs_diff[11]),
  .gpr_12             (regs_diff[12]),
  .gpr_13             (regs_diff[13]),
  .gpr_14             (regs_diff[14]),
  .gpr_15             (regs_diff[15]),
  .gpr_16             (regs_diff[16]),
  .gpr_17             (regs_diff[17]),
  .gpr_18             (regs_diff[18]),
  .gpr_19             (regs_diff[19]),
  .gpr_20             (regs_diff[20]),
  .gpr_21             (regs_diff[21]),
  .gpr_22             (regs_diff[22]),
  .gpr_23             (regs_diff[23]),
  .gpr_24             (regs_diff[24]),
  .gpr_25             (regs_diff[25]),
  .gpr_26             (regs_diff[26]),
  .gpr_27             (regs_diff[27]),
  .gpr_28             (regs_diff[28]),
  .gpr_29             (regs_diff[29]),
  .gpr_30             (regs_diff[30]),
  .gpr_31             (regs_diff[31])
);

DifftestTrapEvent DifftestTrapEvent(
  .clock              (clock),
  .coreid             (0),
  .valid              (trap),
  .code               (trap_code),
  .pc                 (cmt_pc),
  .cycleCnt           (cycleCnt),
  .instrCnt           (instrCnt)
);

DifftestCSRState DifftestCSRState(
  .clock              (clock),
  .coreid             (0),
  .priviledgeMode     (`RISCV_PRIV_MODE_M),
  .mstatus            (mstatus_diff),//mstatus_diff
  .sstatus            (sstatus_diff),
  .mepc               (mepc_diff),//mepc_diff
  .sepc               (0),
  .mtval              (0),
  .stval              (0),
  .mtvec              (mtvec_diff),//mtvec_diff
  .stvec              (0),
  .mcause             (mcause_diff),//mcause_diff
  .scause             (0),
  .satp               (0),
  .mip                (mip_diff),//mip_diff
  .mie                (mie_diff),//mie_diff
  .mscratch           (mscratch_diff),
  .sscratch           (0),
  .mideleg            (0),
  .medeleg            (0)
);

DifftestArchFpRegState DifftestArchFpRegState(
  .clock              (clock),
  .coreid             (0),
  .fpr_0              (0),
  .fpr_1              (0),
  .fpr_2              (0),
  .fpr_3              (0),
  .fpr_4              (0),
  .fpr_5              (0),
  .fpr_6              (0),
  .fpr_7              (0),
  .fpr_8              (0),
  .fpr_9              (0),
  .fpr_10             (0),
  .fpr_11             (0),
  .fpr_12             (0),
  .fpr_13             (0),
  .fpr_14             (0),
  .fpr_15             (0),
  .fpr_16             (0),
  .fpr_17             (0),
  .fpr_18             (0),
  .fpr_19             (0),
  .fpr_20             (0),
  .fpr_21             (0),
  .fpr_22             (0),
  .fpr_23             (0),
  .fpr_24             (0),
  .fpr_25             (0),
  .fpr_26             (0),
  .fpr_27             (0),
  .fpr_28             (0),
  .fpr_29             (0),
  .fpr_30             (0),
  .fpr_31             (0)
);

endmodule

